
package com.phevos.common.util;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class TaskThreadPool extends ThreadGroup
{
    private static final int MAX_THREAD_NUMBER = 88;

    private static LinkedList taskPool;

    private static List threadpool;

    // private static Object monitor_pool = new Object();
    private static Logger logger = LoggerFactory.getLogger("TaskThreadPool");

    private static TaskThreadPool pool = new TaskThreadPool();

    private static boolean isAlive;

    private TaskThreadPool()
    {
        super("TaskThreadPool"); // ע�����������
        this.setDaemon(true); // ��̨����

        isAlive = true;
        taskPool = new LinkedList();
        threadpool = new ArrayList(MAX_THREAD_NUMBER);
        for (int i = 0; i < MAX_THREAD_NUMBER; i++)
        {
            PooledTaskThread thread = new PooledTaskThread("TaskThread-" + i);
            threadpool.add(thread);
            thread.start();
        }
    }

    public synchronized static TaskThreadPool getInstance()
    {
        return pool;
    }

 
    public synchronized void registTask(Task task)
    {
        if (!isAlive)
        {
            throw new IllegalStateException();
        }
        if (task != null)
        {
            String identifier = task.getIdentifier();
            logger.debug("############### Regesit Task:" + identifier);
            Task t = null;
            if (task.isbestrow())// �ж������Ƿ������?���ǵ�
                t = findHoldingTask(identifier);
            if (t != null)
            {
                logger.debug("############### Task: {} exit",identifier);
            }
            else
            {
                taskPool.add(task);
            }
        
            notifyAll();
        }
    }

    /**
     * ��ȡ����
     * 
     * @throws InterruptedException
     * @return Task
     */
    protected synchronized Task getTask() throws InterruptedException
    {
        while (taskPool.size() == 0)
        {
            if (!isAlive)
                return null;
            wait();
        }
        return (Task)taskPool.removeFirst(); // ��ȡ��һ����������е�����
    }

    /**
     * �ڵ�ǰ�ĵȴ�����в�������
     * 
     * @param ident String
     * @return TaskThread
     */
    public synchronized Task findHoldingTask(String ident)
    {
        Task holdingTask = null;
        Iterator i = taskPool.iterator();
        Task t = null;
        while (i.hasNext())
        {
            t = (Task)i.next();
            if (t.getIdentifier() == ident)
            {
                holdingTask = t;
                break;
            }
        }
        return holdingTask;
    }

    /**
     * �����ж����л���������е�����
     * 
     * @param ident String
     * @return TaskThread
     */
    public synchronized PooledTaskThread findRunningTask(String ident)
    {
        PooledTaskThread runningTask = null;
        Iterator i = threadpool.iterator();
        PooledTaskThread t = null;
        while (i.hasNext())
        {
            t = (PooledTaskThread)i.next();
            if (t.getIdentifier() == ident)
            {
                runningTask = t;
                break;
            }
        }
        return runningTask;
    }

    /**
     * �ر������̳�
     */
    public synchronized void close()
    {
        if (!isAlive)
        {
            taskPool.clear();
            threadpool.clear();
            interrupt();
        }
    }

    /**
     * @param ident String
     */
    public void join()
    {
        synchronized (this)
        {
            isAlive = false;
            notifyAll();
        }
        Thread[] threads = new Thread[activeCount()];
        int count = enumerate(threads);
        for (int i = 0; i < count; i++)
        {
            try
            {
                threads[i].join();
            }
            catch (InterruptedException ex)
            {
            }
        }
    }


    public synchronized void checkingTask(String ident)
    {
        PooledTaskThread task = findRunningTask(ident);
       
        if (task != null && task.getStatus() == PooledTaskThread.TASK_RUNNING)
        {
            killTaskThread(ident);
        }
    }

   
    private synchronized void killTaskThread(String ident)
    {
        PooledTaskThread timeoutTask = null;
        timeoutTask = findRunningTask(ident);
        logger.debug("Task " + timeoutTask.getPooledTask().getIdentifier()
                        + " has Runing Timeout.");
        timeoutTask.killTask(); //
        timeoutTask.interrupt(); // �жϽ��
        timeoutTask.destroy(); // �ƻ�����
        timeoutTask.start();
    }

    public class PooledTaskThread extends Thread
    {
        // private static Logger logger = LoggerFactory.getLogger("TaskThread");
        private static final int second = 1000;

        public static final int TASK_HOLDING = 0;

        public static final int TASK_RUNNING = 1;

        public static final int TASK_TIMEOUT = 2;

        private Task task = null;

        private String ident = null;

        private int status = TASK_HOLDING;

        private String id = null;

       
        public PooledTaskThread(String threadID)
        {
            super(TaskThreadPool.getInstance(), "TaskThread-" + threadID);
            id = threadID;
        }

        /**
         * ���з���
         */
        public void run()
        {
            while (!isInterrupted())
            {
                // ��������Ѿ�������ɱ�������
                if (task != null)
                    killTask();
                // ���»�ȡ����
                try
                {
                    task = getTask();
                }
                catch (InterruptedException ie)
                {
                    logger.debug("############### TaskThread-" + id
                            + " has weak up and receive task:" + task.getIdentifier());
                }

                // �������Ϊ���򷵻�ʲô������
                if (task == null)
                {
                    return;
                }
                // �������������ע������
                ident = task.getIdentifier() + "->" + System.currentTimeMillis();
                TaskThreadPoolManager.getInstance().registTask(ident, getWeakUpTime());
                // ִ������
                try
                {
                    status = TASK_RUNNING; // ��ʾ��ʶ��ǰ��������״̬
                    task.run();
                }
                catch (Throwable t)
                {
                    logger.error("TaskThread Running task Error.", t);
                }
            }
        }

        /**
         * ����ȡ�������������ʱ��
         * 
         * @return long
         */
        private long getWeakUpTime()
        {
            if (task.maxExecuteTime > 0)
            {
                long curr = System.currentTimeMillis();
                return curr + task.maxExecuteTime * second;
            }
            else
                return 0;
        }

        /**
         * ɱ��ǰ����е�����
         */
        public void killTask()
        {
            task.clear();
            task = null;
            ident = null;
            status = TASK_HOLDING;
        }

        /**
         * ��õ�ǰ�������������е�����
         * 
         * @return Task
         */
        public Task getPooledTask()
        {
            return task;
        }

        /**
         * ȡ�������̵�Ψһ��ʶ
         * 
         * @return String
         */
        public String getIdentifier()
        {
            return ident;
        }

        /**
         * ���ص�ǰ�����̵�״̬
         * 
         * @return int
         */
        public int getStatus()
        {
            return status;
        }
    }

}
